// ignore_for_file: must_be_immutable

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kmxy_base/page/map_select/map_select_page_view.dart';
import 'package:kmxy_base/util/string_util.dart';
import 'package:kmxy_base/util/us_double_textInput_formatter.dart';
import 'package:kmxy_base/util/us_int_textInput_formatter.dart';
import 'package:kmxy_base/widget/dialog_factory.dart';

typedef OnCallBack = void Function();
typedef OnStringCallBack = void Function(String data);
typedef OnMapCallBack = void Function(Map data);

class FormWidget extends StatefulWidget {
  /// ------------------公共参数------------------

  /// 是否显示星号，默认：false
  bool isStar;

  /// 星号样式，默认：Colors.red，16.sp
  TextStyle? starStyle;

  /// 左边文字样式，默认：Colors.grey，16.sp
  TextStyle? leftTextStyle;

  /// 右边文字样式，默认：Colors.black，16.sp
  TextStyle? rightTextStyle;

  /// 左边数据
  String leftData;

  /// 右边数据，传入一个map，用rightValue区别
  Map rightData;

  /// 右边数据key值
  String? rightKey;

  /// 右边数据value值
  String rightValue;

  /// 表单类型，-1，显示文本，0 输入框，1 Map选择（单选），2 时间选择，3 带搜索Map选择（单选），4 地址选择，5 描述输入框，6 勾选框，7 输入选择
  int type;

  /// 表单是否可以编辑，true 可以编辑，false 不能编辑，默认：true
  bool isEdit;

  /// 变化回调通知
  OnCallBack? onCallBack;

  /// 变化回调通知
  OnStringCallBack? onStringCallBack;

  /// 变化回调通知
  OnMapCallBack? onMapCallBack;

  /// 外部选择，只对-1，显示文本起作用
  Function? selectFun;

  /// 多行显示,只对-1，默认单行
  bool isMoreLine;

  /// 左边宽度
  double? leftWidth;

  /// 右边宽度
  double? rightWidth;

  /// ------------------输入框参数------------------

  /// 输入框文字提示样式，默认：Colors.grey，16.sp
  TextStyle? hintStyle;

  /// 输入框文字提示，默认：请输入
  String? hintText;

  /// 输入类型 0 文本，1 整数，2 小数
  int inputType;

  /// 是否是密码模式，默认：false
  bool isPassword;

  /// 输入框控制器
  TextEditingController? controller;

  /// 小数位数
  int? decimalNum;

  /// ------------------Map选择（单选）参数------------------

  /// Map选择列表数据
  List? selectList;

  /// Map选择列表数据选择的key
  String? selectListKey;

  /// Map选择列表数据显示的value
  String? selectListName;

  bool isMapSearch;

  /// ------------------时间选择参数------------------

  /// true 日期时间选择，false 日期选择，默认：true
  bool isTime;

  /// 最小时间
  DateTime? minTime;

  /// 最大时间
  DateTime? maxTime;

  /// 时间格式化
  String? timeFormat;

  /// 是否选择秒
  bool isSelectSecond;

  /// --------------地图选择参数--------------
  String amapAndroidKey;
  String amapiOSKey;

  /// --------------选择框参数--------------
  String? yes;
  String? no;

  FormWidget({
    Key? key,
    this.isStar = false,
    this.starStyle,
    this.inputType = 0,
    this.leftTextStyle,
    this.rightTextStyle,
    this.hintStyle,
    this.hintText,
    required this.leftData,
    required this.rightData,
    required this.rightValue,
    this.type = 0,
    this.isEdit = true,
    this.selectList,
    this.selectListKey,
    this.selectListName,
    this.rightKey,
    this.isTime = true,
    this.minTime,
    this.maxTime,
    this.onCallBack,
    this.onStringCallBack,
    this.onMapCallBack,
    this.isPassword = false,
    this.controller,
    this.timeFormat,
    this.selectFun,
    this.isMoreLine = false,
    this.isMapSearch = false,
    this.amapAndroidKey = '',
    this.amapiOSKey = '',
    this.isSelectSecond = false,
    this.leftWidth,
    this.rightWidth,
    this.yes = '1',
    this.no = '0',
    this.decimalNum,
  }) : super(key: key);

  @override
  _FormWidget createState() => _FormWidget();
}

class _FormWidget extends State<FormWidget> {
  /// --------------显示文本---------------
  textWidget() {
    return SizedBox(
        width: widget.rightWidth ?? 160.w,
        child: Text(
            widget.timeFormat != null
                ? timeFormatF(widget.rightData[widget.rightValue] ?? '')
                : '${widget.rightData[widget.rightValue] ?? ''}',
            textAlign: TextAlign.right,
            style: widget.rightTextStyle ??
                TextStyle(color: Colors.black, fontSize: 16.sp)));
  }

  /// --------------输入框---------------

  late TextEditingController controller;

  /// 键盘类型，0 文本，1 整数，2 小数
  TextInputType inputTypeF() {
    if (widget.inputType == 1) return TextInputType.number;
    if (widget.inputType == 2) return const TextInputType.numberWithOptions(decimal: true);
    return TextInputType.text;
  }

  /// 限定输入类型 0 文本，1 整数，2 小数
  List<TextInputFormatter>? inputFormattersF() {
    if (widget.inputType == 1) {
      return [
        FilteringTextInputFormatter.allow(RegExp("[0-9]")),
        UsIntTextInputFormatter(),
      ];
    }
    if (widget.inputType == 2) {
      return [
        FilteringTextInputFormatter.allow(widget.decimalNum == null
            ? RegExp("[0-9.]")
            : RegExp(r'(^\d*\.?\d{0,'
                '${widget.decimalNum}'
                '})')),
        UsDoubleTextInputFormatter(),
      ];
    }
    return null;
  }

  /// 输入框
  Widget textField() {
    return SizedBox(
      width: 160.w,
      child: TextField(
        enabled: widget.isEdit,
        autofocus: false,
        obscureText: widget.isPassword,
        keyboardType: inputTypeF(),
        inputFormatters: inputFormattersF(),
        onChanged: (String text) {
          widget.rightData[widget.rightValue] = text;
          if (widget.onCallBack != null) widget.onCallBack!();
          if (widget.onStringCallBack != null) widget.onStringCallBack!(text);
          if (widget.type == 0 || widget.type == 4 || widget.type == 5) {
            widget.rightData[widget.rightValue] = text;
          }
        },
        controller: controller,
        textAlign: TextAlign.end,
        maxLines: 1,
        style: widget.rightTextStyle ??
            TextStyle(color: Colors.black, fontSize: 16.sp),
        decoration: InputDecoration(
            isCollapsed: true, // 包裹内容来设置TextField高度
            hintStyle: widget.hintStyle ??
                TextStyle(color: Colors.grey, fontSize: 16.sp),
            hintText: widget.hintText ?? '请输入',
            border: InputBorder.none),
      ),
    );
  }

  /// 输入框-多行
  Widget textFieldMore() {
    return SizedBox(
      width: 370.w,
      child: TextField(
        enabled: widget.isEdit,
        autofocus: false,
        obscureText: widget.isPassword,
        maxLength: 500,
        keyboardType: TextInputType.multiline,
        inputFormatters: inputFormattersF(),
        maxLines: 5,
        onChanged: (String text) {
          widget.rightData[widget.rightValue] = text;
          if (widget.onCallBack != null) widget.onCallBack!();
          if (widget.onStringCallBack != null) widget.onStringCallBack!(text);
          if (widget.type == 5 || widget.type == 4) {
            widget.rightData[widget.rightValue] = text;
          }
        },
        controller: controller,
        style: widget.rightTextStyle ??
            TextStyle(color: Colors.black, fontSize: 16.sp),
        decoration: InputDecoration(
            isCollapsed: true, // 包裹内容来设置TextField高度
            hintStyle: widget.hintStyle ??
                TextStyle(color: Colors.grey, fontSize: 16.sp),
            hintText: widget.hintText ?? '请输入',
            border: InputBorder.none),
      ),
    );
  }

  /// 输入框-多行-文本显示
  Widget textFieldMoreText() {
    return SizedBox(
      width: 370.w,
      child: Text(
          widget.timeFormat != null
              ? timeFormatF(widget.rightData[widget.rightValue] ?? '')
              : '${widget.rightData[widget.rightValue] ?? ''}',
          textAlign: TextAlign.left,
          style: widget.rightTextStyle ??
              TextStyle(color: Colors.black, fontSize: 16.sp)),
    );
  }

  /// --------------Map选择（单选）--------------
  /// --------------时间选择--------------

  /// 所选索引
  int selectMapIndex = 0;

  /// 选择Widget
  Widget selectWidget() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        SizedBox(
          width: widget.rightWidth ?? 150.w,
          child: Text(
            widget.timeFormat != null
                ? (timeFormatF(widget.rightData[widget.rightValue] ??
                    ((widget.selectFun != null || widget.type == 2)
                        ? '请选择'
                        : '')))
                : widget.rightData[widget.rightValue] ??
                    ((widget.selectFun != null || widget.type == 2)
                        ? '请选择'
                        : ''),
            textAlign: TextAlign.end,
            style: widget.rightTextStyle ??
                TextStyle(color: Colors.black, fontSize: 16.sp),
          ),
        ),
        widget.isEdit
            ? Icon(Icons.keyboard_arrow_down,
                size: 20.sp,
                color: widget.leftTextStyle == null
                    ? Colors.black
                    : widget.leftTextStyle?.color ?? Colors.black)
            : Container(),
      ],
    );
  }

  /// 勾选框
  Widget yesNoWidget() {
    return SizedBox(
      width: widget.rightWidth ?? 150.w,
      child: widget.isEdit
          ? Checkbox(
              activeColor: Colors.black,
              value: (widget.rightData[widget.rightValue] ?? widget.no) ==
                  widget.yes,
              onChanged: (value) {
                if (widget.isEdit) {
                  widget.rightData[widget.rightValue] =
                      value == true ? widget.yes : widget.no;
                  setState(() {});
                }
              },
            )
          : ((widget.rightData[widget.rightValue] ?? widget.no) == widget.yes
              ? const Icon(Icons.check)
              : Container()),
    );
  }

  /// 勾选框选择方法
  selectYesNoF(BuildContext context) {
    if (!widget.isEdit) {
      return;
    }
    // 收起键盘，失去焦点
    FocusManager.instance.primaryFocus?.unfocus();
    widget.rightData[widget.rightValue] =
        widget.rightData[widget.rightValue] == widget.yes
            ? widget.no
            : widget.yes;
    setState(() {});
    if (widget.onCallBack != null) widget.onCallBack!();
  }

  /// Map选择（单选）方法
  selectMapF(BuildContext context) {
    // 收起键盘，失去焦点
    FocusManager.instance.primaryFocus?.unfocus();
    if (widget.selectList == null || widget.selectList!.isEmpty) {
      '选择列表为空（selectList）'.toast();
      return;
    }
    if (widget.selectListKey == null || widget.selectListKey!.isEmpty) {
      '选择列表key为空（selectListKey）'.toast();
      return;
    }
    if (widget.selectListName == null || widget.selectListName!.isEmpty) {
      '选择列表显示名称name为空（selectListName）'.toast();
      return;
    }
    if (widget.selectListName == null || widget.selectListName!.isEmpty) {
      '右边数据key为空（rightKey）'.toast();
      return;
    }
    if (widget.isMapSearch) {
      DialogFactory.pickerSearchMap(
          context, widget.selectList!, widget.selectListName!,
          onConfirm: (confirmData, mIndex) {
        widget.rightData[widget.rightKey] = confirmData[widget.selectListKey];
        widget.rightData[widget.rightValue] =
            confirmData[widget.selectListName];
        if (widget.onCallBack != null) widget.onCallBack!();
        if (widget.onMapCallBack != null) widget.onMapCallBack!(confirmData);
      }, onCancel: () {});
    } else {
      DialogFactory.pickerMap(
          context, widget.selectList!, widget.selectListName!,
          initialItem: selectMapIndex, onConfirm: (confirmData, mIndex) {
        selectMapIndex = mIndex;
        widget.rightData[widget.rightKey] = confirmData[widget.selectListKey];
        widget.rightData[widget.rightValue] =
            confirmData[widget.selectListName];
        if (widget.onCallBack != null) widget.onCallBack!();
        if (widget.onMapCallBack != null) widget.onMapCallBack!(confirmData);
      }, onCancel: () {});
    }
  }

  /// Map选择（单选）,带搜索方法
  selectSearchMapF(BuildContext context) {
    // 收起键盘，失去焦点
    FocusManager.instance.primaryFocus?.unfocus();
    if (widget.selectList == null || widget.selectList!.isEmpty) {
      '选择列表为空（selectList）'.toast();
      return;
    }
    if (widget.selectListKey == null || widget.selectListKey!.isEmpty) {
      '选择列表key为空（selectListKey）'.toast();
      return;
    }
    if (widget.selectListName == null || widget.selectListName!.isEmpty) {
      '选择列表显示名称name为空（selectListName）'.toast();
      return;
    }
    if (widget.selectListName == null || widget.selectListName!.isEmpty) {
      '右边数据key为空（rightKey）'.toast();
      return;
    }
    DialogFactory.pickerSearchMap(
        context, widget.selectList!, widget.selectListName!,
        onConfirm: (confirmData, mIndex) {
      widget.rightData[widget.rightKey] = confirmData[widget.selectListKey];
      widget.rightData[widget.rightValue] = confirmData[widget.selectListName];
      if (widget.onCallBack != null) widget.onCallBack!();
      if (widget.onMapCallBack != null) widget.onMapCallBack!(confirmData);
    }, onCancel: () {});
  }

  @override
  void initState() {
    controller = widget.controller ?? TextEditingController();
    if (widget.type == 0 || widget.type == 4 || widget.type == 5) {
      controller.text = widget.rightData[widget.rightValue] ?? '';
    }
    super.initState();
  }

  /// 时间选择方法
  selectTimeF(BuildContext context) {
    // 收起键盘，失去焦点
    FocusManager.instance.primaryFocus?.unfocus();
    if (widget.isTime) {
      DialogFactory.dateTimeSelect(context,
          isSelectSecond: widget.isSelectSecond,
          minTime: widget.minTime,
          maxTime: widget.maxTime, onTime: (time) {
        widget.rightData[widget.rightValue] = time;
        if (widget.onCallBack != null) widget.onCallBack!();
        if (widget.onStringCallBack != null) widget.onStringCallBack!(time);
      });
    } else {
      DialogFactory.dateSelect(context,
          minTime: widget.minTime, maxTime: widget.maxTime, onTime: (time) {
        widget.rightData[widget.rightValue] = time;
        if (widget.onCallBack != null) widget.onCallBack!();
        if (widget.onStringCallBack != null) widget.onStringCallBack!(time);
      });
    }
  }

  /// --------------地图选择--------------

  /// 选择Widget
  Widget selectMapWidget() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        SizedBox(
          width: widget.rightWidth ?? 150.w,
          child: Text(
            '地图选择',
            textAlign: TextAlign.end,
            style: widget.rightTextStyle ??
                TextStyle(color: Colors.black, fontSize: 16.sp),
          ),
        ),
        widget.isEdit
            ? Icon(Icons.keyboard_arrow_down,
                size: 20.sp,
                color: widget.leftTextStyle == null
                    ? Colors.black
                    : widget.leftTextStyle?.color ?? Colors.black)
            : Container(),
      ],
    );
  }

  Map mapData = {};

  /// 跳转地图
  selectMap(BuildContext context) async {
    Map? callData = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (_) {
          return MapSelectPage(arguments: {
            'amapAndroidKey': widget.amapAndroidKey,
            'amapiOSKey': widget.amapiOSKey,
          });
        },
      ),
    );
    mapData = callData ?? {};
    if (mapData.isNotEmpty) {
      controller.text = mapData['address'] ?? '';
      setState(() {});
      if (widget.onCallBack != null) widget.onCallBack!();
      if (widget.onMapCallBack != null) widget.onMapCallBack!(mapData);
    }
  }

  @override
  void dispose() {
    controller.clear();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if ((widget.type == 0 ||
        widget.type == 4 ||
        widget.type == 5 ||
        widget.type == 7)) {
      controller.value = TextEditingValue(
        text: widget.rightData[widget.rightValue] ?? '',
        selection: TextSelection.fromPosition(
          TextPosition(
            affinity: TextAffinity.downstream,
            offset: (widget.rightData[widget.rightValue] ?? '').length,
          ),
        ),
      );
    }
    Widget topView = Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        SizedBox(
          width: widget.leftWidth,
          child: Text.rich(
            TextSpan(
              text: widget.leftData,
              style: widget.leftTextStyle ??
                  TextStyle(color: Colors.grey, fontSize: 16.sp),
              children: <TextSpan>[
                if (widget.isStar)
                  TextSpan(
                    text: ' * ',
                    style: widget.starStyle ??
                        TextStyle(color: Colors.red, fontSize: 16.sp),
                  ),
              ],
            ),
          ),
        ),
        Expanded(child: Container()),
        rightWidget(),
      ],
    );

    Widget bottomView = Container(
      color: Colors.white,
      padding: EdgeInsets.only(
        top: 5.w,
        bottom: 6.w,
      ),
      child: widget.type == 4
          ? TextField(
              autofocus: false,
              onChanged: (String text) {
                mapData['address'] = text.trim();
                if (widget.onCallBack != null) {
                  widget.onCallBack!();
                }
                if (widget.onStringCallBack != null) {
                  widget.onMapCallBack!(mapData);
                }
                if (widget.type == 0 || widget.type == 4 || widget.type == 5) {
                  widget.rightData[widget.rightValue] = text;
                }
              },
              controller: controller,
              maxLines: 2,
              style: widget.rightTextStyle ??
                  TextStyle(color: Colors.black, fontSize: 16.sp),
              decoration: InputDecoration(
                  isCollapsed: true, // 包裹内容来设置TextField高度
                  hintStyle: widget.hintStyle ??
                      TextStyle(color: Colors.grey, fontSize: 16.sp),
                  hintText: widget.hintText ?? '请输入',
                  border: InputBorder.none),
            )
          : Text(
              widget.timeFormat != null
                  ? timeFormatF(widget.rightData[widget.rightValue] ?? '')
                  : '${widget.rightData[widget.rightValue] ?? ''}',
              style: widget.rightTextStyle ??
                  TextStyle(color: Colors.black, fontSize: 16.sp),
            ),
    );
    bool isMoreLine = widget.isMoreLine;
    if (widget.type == 4) {
      isMoreLine = true;
    }

    Widget msView = Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (widget.leftData.isNotEmpty)
          SizedBox(
            width: widget.leftWidth,
            child: Text.rich(
              TextSpan(
                text: widget.leftData,
                style: widget.leftTextStyle ??
                    TextStyle(color: Colors.grey, fontSize: 16.sp),
                children: <TextSpan>[
                  if (widget.isStar)
                    TextSpan(
                      text: ' * ',
                      style: widget.starStyle ??
                          TextStyle(color: Colors.red, fontSize: 16.sp),
                    ),
                ],
              ),
            ),
          ),
        if (widget.leftData.isNotEmpty) SizedBox(height: 10.w),
        rightWidget(),
      ],
    );

    return InkWell(
      onTap: () => itemClick(context),
      child: Container(
        color: Colors.white,
        padding: EdgeInsets.symmetric(vertical: 12.w, horizontal: 8.w),
        child: isMoreLine
            ? Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [topView, SizedBox(height: 5.w), bottomView],
              )
            : (widget.type == 5 ? msView : topView),
      ),
    );
  }

  /// 表单类型，-1，显示文本，0 输入框，1 Map选择（单选），2 时间选择，3 带搜索Map选择（单选）
  Widget rightWidget() {
    if (widget.type == -1) {
      if (widget.selectFun != null) {
        return selectWidget();
      } else {
        if (widget.isMoreLine) {
          return Container();
        } else {
          return textWidget();
        }
      }
    }

    if (widget.type == 1) return selectWidget();
    if (widget.type == 2) return selectWidget();
    if (widget.type == 3) return selectWidget();
    if (widget.type == 4) return selectMapWidget();
    if (widget.type == 5) {
      return widget.isEdit ? textFieldMore() : textFieldMoreText();
    }
    if (widget.type == 6) return yesNoWidget();
    if (widget.type == 7) return inputSelectWidget();
    return textField();
  }

  // 表单条目点击
  itemClick(BuildContext context) {
    if (!widget.isEdit) return;
    if (widget.type == -1 && widget.selectFun != null) widget.selectFun!();
    if (widget.type == 0) return;
    if (widget.type == 1) selectMapF(context);
    if (widget.type == 2) selectTimeF(context);
    if (widget.type == 3) selectSearchMapF(context);
    if (widget.type == 4) selectMap(context);
    if (widget.type == 5) return;
    if (widget.type == 6) selectYesNoF(context);
    if (widget.type == 7) inputSelectF(context);
  }

  /// 输入框
  Widget inputSelectWidget() {
    return Row(
      children: [
        SizedBox(
          width: 160.w,
          child: TextField(
            enabled: widget.isEdit,
            autofocus: false,
            obscureText: widget.isPassword,
            keyboardType: inputTypeF(),
            inputFormatters: inputFormattersF(),
            onChanged: (String text) {
              widget.rightData[widget.rightValue] = text;
              if (widget.onCallBack != null) widget.onCallBack!();
              if (widget.onStringCallBack != null)
                widget.onStringCallBack!(text);
              if (widget.type == 0 || widget.type == 4 || widget.type == 5) {
                widget.rightData[widget.rightValue] = text;
              }
            },
            controller: controller,
            textAlign: TextAlign.end,
            maxLines: 1,
            style: widget.rightTextStyle ??
                TextStyle(color: Colors.black, fontSize: 16.sp),
            decoration: InputDecoration(
                isCollapsed: true, // 包裹内容来设置TextField高度
                hintStyle: widget.hintStyle ??
                    TextStyle(color: Colors.grey, fontSize: 16.sp),
                hintText: widget.hintText ?? '请输入',
                border: InputBorder.none),
          ),
        ),
        Icon(Icons.keyboard_arrow_down),
      ],
    );
  }

  inputSelectF(BuildContext context) {
    if (widget.selectFun != null) {
      widget.selectFun!();
    }
  }

  /// 时间数据格式化方法
  /// yyyy-MM-dd hh:mm:ss
  String timeFormatF(String rightData) {
    String tempTime = rightData;
    if (widget.isTime) {
      if (tempTime.length < 19) {
        return tempTime;
      }
      if (!widget.timeFormat!.contains('ss')) {
        // yyyy-MM-dd hh:mm
        return tempTime.substring(0, 16);
      } else if (!widget.timeFormat!.contains('mm')) {
        // yyyy-MM-dd hh
        return tempTime.substring(0, 13);
      }
    } else {
      if (tempTime.length < 10) {
        return tempTime;
      }
      if (!widget.timeFormat!.contains('hh')) {
        // yyyy-MM-dd
        return tempTime.substring(0, 10);
      } else if (!widget.timeFormat!.contains('dd')) {
        // yyyy-MM
        return tempTime.substring(0, 7);
      } else if (!widget.timeFormat!.contains('MM')) {
        // yyyy
        return tempTime.substring(0, 4);
      }
    }

    return tempTime;
  }
}
